﻿#include "ctpdatastorage.h"

QMutex CTPDataStorage::s_mutex[WORK_QUEUE];
QQueue<QStringList> CTPDataStorage::s_dataQueue[WORK_QUEUE];
QSemaphore CTPDataStorage::s_sempData[WORK_QUEUE];
//储存1分钟K线的相关变量
QMap<QString,KLineType*> CTPDataStorage::s_Map1MinKLine[WORK_QUEUE];
QMutex CTPDataStorage::s_mutex1MinKLine[WORK_QUEUE];
//储存5分钟K线的相关变量
QMap<QString,KLineType*> CTPDataStorage::s_Map5MinKLine[WORK_QUEUE];
QMutex CTPDataStorage::s_mutex5MinKLine[WORK_QUEUE];
//储存1小时K线的相关变量
QMap<QString,KLineType*> CTPDataStorage::s_Map1HourKLine[WORK_QUEUE];
QMutex CTPDataStorage::s_mutex1HourKLine[WORK_QUEUE];

CTPDataStorage::CTPDataStorage()
{

}

CTPDataStorage::~CTPDataStorage()
{

}

void CTPDataStorage::GetData(QStringList &strList, int nIndex)
{
    s_sempData[nIndex].acquire();
    s_mutex[nIndex].lock();

    /*if(s_dataList[nIndex].size() > 0) {
        strList = s_dataList[nIndex].at(0);
        s_dataList[nIndex].pop_front();
    }*/
    if(!s_dataQueue[nIndex].isEmpty()){
        strList = s_dataQueue[nIndex].dequeue();
    }

    s_mutex[nIndex].unlock();
}

void CTPDataStorage::SetData(QStringList &strList, int nIndex)
{
    s_mutex[nIndex].lock();
    s_sempData[nIndex].release();

    //s_dataList[nIndex].push_back(strList);
    s_dataQueue[nIndex].enqueue(strList);

    s_mutex[nIndex].unlock();
}
//保存5分钟K线数据
void CTPDataStorage::Save5MinKLineData(OracleDAO &dao,QMap<QString,QString> &mapZhulian,QMap<QString,QString> &mapJinyue ,QMap<QString,ContractType> &MapContractType)
{
    QString date = QDate::currentDate().toString("yyyyMMdd");//获取当前日期
    for(int nIndex = 0; nIndex < WORK_QUEUE; nIndex++){
        QString time = QTime::currentTime().toString("hh:mm:ss");//获取当前时间

        QMap<QString,KLineType*>::iterator it; //遍历map
        for ( it = (s_Map5MinKLine[nIndex]).begin(); it != (s_Map5MinKLine[nIndex]).end(); ++it ) {
            QString strInstrumentID = it.key();
            KLineType* KLine = it.value();
            s_mutex5MinKLine[nIndex].lock();
            if(KLine->bUpdateFlg == true){
                if(KLine->StartVolume != KLine->EndVolume){//有成交的话 才保存K线数据
                    ///插入5分钟K线数据
                    dao.Insert5MinRec(strInstrumentID,KLine,date,time);
                    ///插入主连的5分钟K线数据
                    if(mapZhulian.contains(strInstrumentID)){
                        dao.InsertZhulian5MinRec(strInstrumentID,KLine,date,time,MapContractType);
                    }
                    ///保存上一根K线的成交量 和 持仓量
                    KLine->PreBusinessAmount = KLine->EndVolume - KLine->StartVolume;
                    KLine->PreOpenInterest   = KLine->OpenInterest;
                }
                KLine->bUpdateFlg = false;
            }
            s_mutex5MinKLine[nIndex].unlock();
        }
    }
    //更新1小时K线数据
    //CTPDataStorage::Update1HourKLineData();
    //判断是否要存储1小时K线
    //CTPDataStorage::Save1HourKLineData(dao,mapZhulian,mapJinyue,MapContractType);
}
//保存1分钟K线数据
void CTPDataStorage::Save1MinKLineData(OracleDAO &dao,QMap<QString,QString> &mapZhulian,QMap<QString,QString> &mapJinyue ,QMap<QString,ContractType> &MapContractType)
{
    QString date = QDate::currentDate().toString("yyyyMMdd");//获取当前日期
    for(int nIndex = 0; nIndex < WORK_QUEUE; nIndex++){
        QString time = QTime::currentTime().toString("hh:mm:ss");//获取当前时间

        QMap<QString,KLineType*>::iterator it; //遍历map
        for ( it = (s_Map1MinKLine[nIndex]).begin(); it != (s_Map1MinKLine[nIndex]).end(); ++it ) {

            QString strInstrumentID = it.key(); //合约名称
            KLineType* KLine = it.value();      //对应的K线数据
            s_mutex1MinKLine[nIndex].lock();
            if(KLine->bUpdateFlg == true){
                if(KLine->StartVolume != KLine->EndVolume){//有成交的话 才保存K线数据
                    dao.Insert1MinRec(strInstrumentID,KLine,date,time);
                    //如果该合约为主连合约 在主连1分钟K线表中 插入一条数据
                    if(mapZhulian.contains(strInstrumentID)){
                        dao.InsertZhulian1MinRec(strInstrumentID,KLine,date,time,MapContractType);
                    }
                    //如果该合约为近月合约 在近月1分钟K线表中 插入一条数据
                    //if(mapJinyue.contains(strInstrumentID)){
                        //dao.Insert1MinRec(mapJinyue[strInstrumentID],KLine,date,time);
                    //}
                }
                KLine->bUpdateFlg = false;
            }
            s_mutex1MinKLine[nIndex].unlock();
        }
    }
}
void CTPDataStorage::Save1HourKLineData(OracleDAO &dao,QMap<QString,QString> &mapZhulian,QMap<QString,QString> &mapJinyue ,QMap<QString,ContractType> &MapContractType)
{

}
void CTPDataStorage::Update1HourKLineData(QString strContract,double lastPrice, int nIndex)
{

}
//更新5分钟K线数据
void CTPDataStorage::Update5MinKLineData(QStringList &szHqList, int nIndex)
{
    QString strContract  = szHqList.at(1);
    double  lastPrice    = szHqList.at(4).toDouble();
    long    volume       = szHqList.at(11).toLong();//成交量
    long    openInterest = szHqList.at(13).toLong();//持仓量

    s_mutex5MinKLine[nIndex].lock();

    if(s_Map5MinKLine[nIndex].contains(strContract)){
        KLineType* KLine = (s_Map5MinKLine[nIndex])[strContract];

        if(KLine->bUpdateFlg == true){
            KLine->ClosePrice = lastPrice;//最新价
            if(lastPrice > KLine->MaxPrice){//更新最高价
                KLine->MaxPrice = lastPrice;
            }
            if(lastPrice < KLine->MinPrice){//更新最低价
                KLine->MinPrice = lastPrice;
            }
            KLine->EndVolume = volume;    //每笔Tick来时 更新成交量
            KLine->OpenInterest     = openInterest;//每笔Tick来时 更新持仓量
            (s_Map5MinKLine[nIndex])[strContract] = KLine;
        }else{
            //每五分钟开始时 记录初始值
            KLine->bUpdateFlg       = true;
            KLine->OpenPrice        = lastPrice;
            KLine->PreClosePrice    = lastPrice;
            KLine->ClosePrice       = lastPrice;
            KLine->MaxPrice         = lastPrice;
            KLine->MinPrice         = lastPrice;
            KLine->StartVolume      = volume;//初始成交量
            KLine->EndVolume        = volume;
            KLine->OpenInterest     = openInterest;

            (s_Map5MinKLine[nIndex])[strContract] = KLine;
        }
    }else{
        KLineType* KLine        = new KLineType();
        KLine->bUpdateFlg       = true;
        KLine->OpenPrice        = lastPrice;
        KLine->PreClosePrice    = lastPrice;
        KLine->ClosePrice       = lastPrice;
        KLine->MaxPrice         = lastPrice;
        KLine->MinPrice         = lastPrice;
        KLine->StartVolume      = volume;
        KLine->EndVolume        = volume;

        (s_Map5MinKLine[nIndex]).insert(strContract,KLine);
    }
    s_mutex5MinKLine[nIndex].unlock();
}

//更新1分钟K线数据
void CTPDataStorage::Update1MinKLineData(QString strContract,double lastPrice,long volume, int nIndex)
{
    s_mutex1MinKLine[nIndex].lock();

    if(s_Map1MinKLine[nIndex].contains(strContract)){
        KLineType* KLine = (s_Map1MinKLine[nIndex])[strContract];

        if(KLine->bUpdateFlg == true){
            KLine->ClosePrice = lastPrice;//最新价
            if(lastPrice > KLine->MaxPrice){//更新最高价
                KLine->MaxPrice = lastPrice;
            }
            if(lastPrice < KLine->MinPrice){//更新最低价
                KLine->MinPrice = lastPrice;
            }
            KLine->EndVolume = volume;    //每笔Tick来时 更新成交量
            (s_Map5MinKLine[nIndex])[strContract] = KLine;
        }else{
            //每1分钟开始时 记录初始值
            KLine->bUpdateFlg       = true;
            KLine->OpenPrice        = lastPrice;
            KLine->PreClosePrice    = lastPrice;
            KLine->ClosePrice       = lastPrice;
            KLine->MaxPrice         = lastPrice;
            KLine->MinPrice         = lastPrice;
            KLine->StartVolume      = volume;//初始成交量
            KLine->EndVolume        = volume;
            (s_Map1MinKLine[nIndex])[strContract] = KLine;
        }
    }else{
        KLineType* KLine        = new KLineType();
        KLine->bUpdateFlg       = true;
        KLine->OpenPrice        = lastPrice;
        KLine->PreClosePrice    = lastPrice;
        KLine->ClosePrice       = lastPrice;
        KLine->MaxPrice         = lastPrice;
        KLine->MinPrice         = lastPrice;
        KLine->StartVolume      = volume;
        KLine->EndVolume        = volume;

        (s_Map1MinKLine[nIndex]).insert(strContract,KLine);
    }
    s_mutex1MinKLine[nIndex].unlock();
}
